from flask import Flask, render_template
from core.exception import ApiException, HTTPException, AdminException, ServerError
from config import Config


def reg_global_error(base_app):
    # 全局异常处理机制
    @base_app.errorhandler(Exception)
    def app_error(e):
        if isinstance(e, ApiException):
            return e
        if not base_app.config.get('DEBUG'):  # 线上
            if isinstance(e, HTTPException):
                status = e.code
                msg = e.description
                code = 1007
                return ApiException(msg, status, code)
            elif isinstance(e, AdminException):
                raise e
            else:
                return ServerError()
        else:
            # debug
            raise e

    # 添加全局404页面
    @base_app.errorhandler(404)
    def page_not_found(error):
        return render_template('404.html'), 404

    # 添加全局401无权限页面
    @base_app.errorhandler(401)
    def unauthorized_access(error):
        return render_template('401.html'), 401


def reg_blugprint(base_app):
    # 注册名为admin的蓝图
    from app.admin import admin as admin_blueprint
    base_app.register_blueprint(admin_blueprint)
    # 注册名为index的蓝图
    from app.index import index as index_blueprint
    base_app.register_blueprint(index_blueprint)
    # 注册/v1和/v2
    from app.api.v1 import create_blueprint_v1
    from app.api.v2 import create_blueprint_v2
    base_app.register_blueprint(create_blueprint_v1(), url_prefix='/api/v1')
    base_app.register_blueprint(create_blueprint_v2(), url_prefix='/api/v2')


def create_app():
    base_app = Flask(__name__, template_folder='./../templates', static_folder='./../static')
    base_app.config.from_object(Config)  # 这个参数有讲究的
    reg_global_error(base_app)
    reg_blugprint(base_app)
    from core.db import db
    db.init_app(base_app)
    from vendor import login_manager
    login_manager.init_app(base_app)
    login_manager.session_protection = 'strong'
    login_manager.blueprint_login_views = {
        'index': "index.index_login",
        'admin': "admin.admin_login",
    }
    from vendor import ckeditor
    ckeditor.init_app(base_app)
    return base_app
